﻿using LJF.Common;
using LJF.Models;
using LJF.Models.Models;
using LJF.MSSQL;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Data;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;

namespace LJF.ManageSYS.Authorize
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
    public class SysAuthorizeAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter
    {
        public string Permission { get; set; }
        public bool Show { get; set; }
        public bool Add { get; set; }
        public bool Update { get; set; }
        public bool Delete { get; set; }
        public bool Output { get; set; }
        public bool Special { get; set; }

        public static HttpRequest httpRequest;

        public SysAuthorizeAttribute()
        {

        }

        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            using (ManageSys_DATAContext dataMD = new ManageSys_DATAContext())
            {
                if (Permission == null) return;

                httpRequest = context.HttpContext.Request;

                var authorizationService = (IAuthorizationService)context.HttpContext.RequestServices.GetService(typeof(IAuthorizationService));
                var authorizationResult = await authorizationService.AuthorizeAsync(context.HttpContext.User, null, new OperationAuthorizationRequirement() { Name = Permission });

                string tokenHeaders = httpRequest.Headers["Authorization"];

                if (tokenHeaders == null) return;

                string userSNo = new JwtSecurityToken(tokenHeaders.Substring(7)).Claims.FirstOrDefault(m => m.Type == "SNo").Value;

                DataTable perList = Dbl.SqlDSN.CreateSqlDataTable(string.Format(@"SELECT u.IsAdmin,per.PermissionName,per._Add,per._Update,per._Delete,per._Show,per._Output,per._Special FROM dbo.XT_User u 
                    LEFT JOIN dbo.[XT_User&Role] ur ON u.SNo=ur.UserSNo 
                    LEFT JOIN dbo.XT_Role r ON r.SNo=ur.RoleSNo
                    LEFT JOIN dbo.[XT_Role&Permission] rp ON ur.RoleSNo=rp.RoleSNo 
                    LEFT JOIN dbo.XT_Permission per ON rp.PermissionSNo=per.SNo 
                    WHERE ur.UserSNo='{0}'", userSNo));

                if (bool.Parse(perList.Rows[0][0].ToString()))
                    return;

                List<XtPermission> permissionList = new List<XtPermission>();
                foreach (DataRow item in perList.Rows)
                {
                    XtPermission per = new XtPermission()
                    {
                        PermissionName = item[1].ToString(),
                        Add = bool.Parse(item[2].ToString()),
                        Update = bool.Parse(item[3].ToString()),
                        Delete = bool.Parse(item[4].ToString()),
                        Show = bool.Parse(item[5].ToString()),
                        Output = bool.Parse(item[6].ToString()),
                        Special = bool.Parse(item[7].ToString())
                    };
                    permissionList.Add(per);
                }

                foreach (var item in permissionList)
                {
                    if (item.PermissionName==Permission)
                    {
                        if ((Show&&item.Show)||
                            (Add&&item.Add)||
                            (Update && item.Update) ||
                            (Delete && item.Delete) ||
                            (Output && item.Output) ||
                            (Special && item.Special))
                        {
                            return;
                        }
                    }
                }

                //无权限
                string url = context.HttpContext.Content("~/api/login/nopermission");
                RedirectResult redirectResult = new RedirectResult(url);
                context.Result = redirectResult;
            }
        }

        /// <summary>
        /// 扩展方法，反射查询所有用到权限控制标签的方法
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return $"\"{base.ToString()}\",\"Permission:{Permission}\",\"Show:{Show}\",\"Add:{Add}\",\"Update:{Update}\",\"Delete:{Delete}\",\"Output:{Output}\",\"Special:{Special}\"";
        }
    }
}
